package ca.uvic.group2.ui;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.util.Date;
import java.lang.*;

import ca.uvic.group2.*;
import ca.uvic.group2.api.*;
import ca.uvic.group2.api.exceptions.*;

import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import java.io.*;
import java.text.*;
import javax.servlet.http.*;
import java.util.ArrayList;
import javax.servlet.*;

class SessionState {
    public long id;
    public String username;
    public String message;

    public SessionState(long id, String username, String message) {
        this.id = id;
        this.username = username;
        this.message = message;
    }

    public SessionState() {
    }
}


public final class StockServ extends HttpServlet implements QuoteCache.QuoteFetcher {

    private static final int CMD_LOGIN = 103149417; //"login".hashCode();
    private static final int CMD_LOGOUT = -1097329270; //"logout".hashCode();
    private static final int CMD_MENU = 3347807; //"menu".hashCode();
    private static final int CMD_QUOTE = 107953788; // "quote".hashCode();
    private static final int CMD_TEST = 3556498; // "test".hashCode();
    private static final int CMD_BUY = 97926; // "buy".hashCode();
    private static final int CMD_CANCEL_BUY = 476579276; //"cancelbuy".hashCode();
    private static final int CMD_COMMIT = -1354815177; // "commit".hashCode();
    private static final int CMD_SELL = 3526482; // "sell".hashCode();
    private static final int CMD_COMMIT_SELL = 1019184393; // "commitsell".hashCode();
    private static final int CMD_CANCEL_SELL = 1889546444; // "cancelsell".hashCode();
    private static final int CMD_ADDFUNDS = -1229325747; //"addfunds".hashCode();
    private static final int CMD_BUY_TRIGGER = 564499570; // "buytrigger".hashCode();
    private static final int CMD_COMMIT_BUY_TRIGGER = -1410865943; // "commitbuytrigger".hashCode();
    private static final int CMD_CANCEL_BUY_TRIGGER = -1933872532; // "cancelbuytrigger".hashCode();
    private static final int CMD_SELL_TRIGGER = 1684473382; // "selltrigger"
    private static final int CMD_COMMIT_SELL_TRIGGER = 577684623; // "commitselltrigger"
    private static final int CMD_CANCEL_SELL_TRIGGER = 1544349548; // "cancelselltrigger"
    private static final int CMD_DISPLAY_STATUS = -759200471; // "display_summary"

    // These commands do not require a valid session id
    private static final int CMD_DUMPLOG = 2009773264; //"dumplog".hashCode();
    private static final int CMD_INIT = 3237136; // "init"
    private static final int CMD_STAT_START = -2072014194; // "statstart"
    private static final int CMD_STAT_STOP = 1318634582; // "statstop"
    private static final int CMD_STAT_GET = -1897138046; // "statget"

    private static final int COOKIE_SESSIONID = 607797809; // "sessionid"
    private static final int COOKIE_STATUS = -892481550; // "status"



    private AuditLog logger;
    private String serverId="StockServ";
    

    static Logger debugLog = Logger.getLogger("StockServ");
    static ServerFactory factory = new ServerFactory();
    static QuoteCache quoteCache = new QuoteCache(debugLog);

    protected void showLoginPage(HttpServletRequest request,
                                 HttpServletResponse response,
                                 String message) throws IOException, ServletException {

        if (message != null) {
            request.setAttribute("errorMessage", message);
        }

        loadJspPage("/login.jsp", request, response);
    }

    protected void showMainMenu(HttpServletRequest request,
                                HttpServletResponse response,
                                SessionState state,
                                int transId) throws IOException,
                                                           ServletException,
                                                           SessionNotFoundException
    {
        final String CMD = "DISPLAY_SUMMARY";
        debugLog.debug(CMD);

        try {
            logger.userDisplaySummary(serverId, transId, state.username);

            TransactionServer xs = factory.getTransactionServer(state.id);
            UserInfo userInfo = xs.getUserInfo(transId, state.id);

            request.setAttribute("userInfo", userInfo);
            if (state.message != null && state.message.length() > 0) {
                request.setAttribute("message", state.message);
            }
            loadJspPage("/mainMenu.jsp", request, response);
        } catch (CommException err) {
            handleError(transId, state, CMD, request, response, err);
        }
    }

    static private Cookie newCookie(String key, String value) {
        Cookie c = new Cookie(key, value);
        c.setPath("/stockserv");
        return c;
    }

    private void setSessionState(SessionState state, HttpServletResponse response) {
        if (state != null) {
            response.addCookie(newCookie("sessionid", Long.toString(state.id) + "." + state.username));
            response.addCookie(newCookie("status", state.message != null ? state.message : ""));
        } else {
            response.addCookie(newCookie("sessionid", ""));
            response.addCookie(newCookie("status", ""));
        }
    }

    private SessionState getSessionState(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null || cookies.length == 0) {
            return null;
        }

        long sessionId = 0L;
        String status = null;
        String username = null;

        for (int i = 0; i < cookies.length; ++i) {
            int name = cookies[i].getName().hashCode();

            switch (name) {
            case COOKIE_SESSIONID :
                sessionId = 0L;
                try {
                    String value = cookies[i].getValue();
                    if (value.length() > 0) {
                        int pos = value.indexOf(".");
                        if (pos > 0) {
                            sessionId = Long.parseLong(value.substring(0, pos));
                            username = value.substring(pos+1);
                        }
                    }
                } catch (NumberFormatException err) {
                    sessionId = 0L;
                }
                break;
            case COOKIE_STATUS :
                status = cookies[i].getValue();
                break;
            }
        }

        if (sessionId != 0L) {
            return new SessionState(sessionId, username, status);
        }
        return null;
    }

    protected void doAddFunds(HttpServletRequest request,
                              HttpServletResponse response) throws IOException, ServletException {


        final String CMD = "ADD";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                float amount = Float.parseFloat(request.getParameter("amount"));

                logger.userAddFunds(serverId, transId, state.username, amount);
                TransactionServer xs = factory.getTransactionServer(state.id);
                xs.addFunds(transId, state.id, amount);
                state.message = "Added $" + Float.toString(amount);
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }

    }

    protected void doCommitBuy(HttpServletRequest request,
                               HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "COMMIT_BUY";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                logger.userCommitBuy(serverId, transId, state.username);
                state.message = null;
                TransactionServer xs = factory.getTransactionServer(state.id);
                Receipt receipt = xs.commitBuy(transId, state.id);

                request.setAttribute("receipt", receipt);
                setSessionState(state, response);
                loadJspPage("/receipt.jsp", request, response);
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doBuy(HttpServletRequest request,
                         HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "BUY";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                String stock = request.getParameter("stock");
                float amount = (Float.valueOf(request.getParameter("amount"))).floatValue();

                logger.userBuy(serverId, transId, state.username, stock, amount);

                TransactionServer xs = factory.getTransactionServer(state.id);

                PurchaseOrder order = xs.buy(transId, state.id, stock, amount);
                state.message = "Order for stock '" + stock + "' is pending.  Press 'Commit Buy' to complete the purchase.";
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doCancelBuy(HttpServletRequest request,
                         HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "CANCEL_BUY";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                logger.userCancelBuy(serverId, transId, state.username);
                TransactionServer xs = factory.getTransactionServer(state.id);
                PurchaseOrder order = xs.cancelBuy(transId, state.id);

                state.message = "Purchase order for '" + order.quote.stock + "' was cancelled.";
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doSell(HttpServletRequest request,
                          HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "SELL";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                String stock = request.getParameter("stock");
                float amount = (Float.valueOf(request.getParameter("amount"))).floatValue();

                logger.userSell(serverId, transId, state.username, stock, amount);

                TransactionServer xs = factory.getTransactionServer(state.id);
                PurchaseOrder order = xs.sell(transId, state.id, stock, amount);

                state.message = "Order to sell stock '" + stock +
                    "' is pending.  Press 'Commit Sell' to complete the purchase.";
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doCancelSell(HttpServletRequest request,
                                HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "CANCEL_SELL";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                logger.userCancelSell(serverId, transId, state.username);

                TransactionServer xs = factory.getTransactionServer(state.id);
                PurchaseOrder order = xs.cancelSell(transId, state.id);

                state.message = "Order to sell '" + order.quote.stock + "' was cancelled.";
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doCommitSell(HttpServletRequest request,
                                HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "COMMIT_SELL";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                logger.userCommitSell(serverId, transId, state.username);

                state.message = null;
                TransactionServer xs = factory.getTransactionServer(state.id);
                Receipt receipt = xs.commitSell(transId, state.id);

                request.setAttribute("receipt", receipt);
                setSessionState(state, response);
                loadJspPage("/receipt.jsp", request, response);
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }


    protected void doDumpLog(HttpServletRequest request, HttpServletResponse response) throws IOException,
                                                                                              ServletException {

        final String CMD = "DUMPLOG";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState) session.getAttribute("State");
        SessionState state = getSessionState(request);

        String userParam = request.getParameter("user");
        boolean forUser = userParam != null && userParam.equals("1");

        try {
            String user = "";
            long id = 0;
            if (state != null) {
                user = state.username;
                id = state.id;
            }
            if (user == "") {
                user = null;
            }


            logger.userDisplayLog(serverId, transId, user, null);
            TransactionServer xs = factory.getTransactionServer(id);
            String logFileName = xs.getLogFile(transId, id, forUser);
            File logFile = new File(logFileName);
            if (logFile.exists() && logFile.isFile()) {

                FileInputStream reader = new FileInputStream(logFile);
                response.setHeader("Content-Type", "application/x-gzip");
                response.addHeader("content-disposition", "attachment; filename=" + logFile.getName());

                ServletOutputStream writer = response.getOutputStream();
                byte[] buf = new byte[10240];
                int len;
                while ((len = reader.read(buf)) > 0) {
                    writer.write(buf, 0, len);
                }
//                 while ((line = reader.readLine()) != null) {
//                     writer.println(line);
//                     //response.flushBuffer();
//                 }

                reader.close();
                logFile.delete();
            } else {
                throw new Exception("Unable to open file: " + logFileName);
            }
        } catch (Exception err) {
            handleError(transId, state, CMD, request, response, err);
        }
    }


    protected void doBuyTrigger(HttpServletRequest request,
                                HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "SET_BUY_AMOUNT";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                state.message = null;
                String stock = request.getParameter("stock");
                float amount = Float.valueOf(request.getParameter("amount")).floatValue();

                logger.userNewBuyTrigger(serverId, transId, state.username, stock, amount);

                TransactionServer xs = factory.getTransactionServer(state.id);

                Trigger trigger = xs.createBuyTrigger(transId, state.id, stock, amount);
                request.setAttribute("trigger", trigger);
                setSessionState(state, response);
                loadJspPage("/buytrigger.jsp", request, response);
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doCommitBuyTrigger(HttpServletRequest request,
                                      HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "SET_BUY_TRIGGER";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                String stock = request.getParameter("stock");
                float price = Float.valueOf(request.getParameter("price")).floatValue();

                logger.userCommitBuyTrigger(serverId, transId, state.username, stock, price);

                TransactionServer xs = factory.getTransactionServer(state.id);

                xs.commitBuyTrigger(transId, state.id, stock, price);
                state.message = "Buy trigger for '" + stock + "' was added.";
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doCancelBuyTrigger(HttpServletRequest request,
                                      HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "CANCEL_SET_BUY";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                String stock = request.getParameter("stock");

                logger.userCancelBuyTrigger(serverId, transId, state.username, stock);

                TransactionServer xs = factory.getTransactionServer(state.id);

                xs.cancelBuyTrigger(transId, state.id, stock);
                state.message = "Buy trigger for '" + stock + "' was cancelled.";
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doSellTrigger(HttpServletRequest request,
                                 HttpServletResponse response) throws IOException, ServletException {

        debugLog.debug("doSellTrigger");
        final String CMD = "SET_SELL_AMOUNT";
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                state.message = null;
                String stock = request.getParameter("stock");
                int amount = Integer.valueOf(request.getParameter("amount")).intValue();

                logger.userNewSellTrigger(serverId, transId, state.username, stock, amount);

                TransactionServer xs = factory.getTransactionServer(state.id);

                Trigger trigger = xs.createSellTrigger(transId, state.id, stock, amount);
                request.setAttribute("trigger", trigger);
                setSessionState(state, response);
                loadJspPage("/selltrigger.jsp", request, response);
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doCommitSellTrigger(HttpServletRequest request,
                                       HttpServletResponse response) throws IOException, ServletException {

        debugLog.debug("doCommitSellTrigger");
        final String CMD = "SET_SELL_TRIGGER";
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                String stock = request.getParameter("stock");
                float price = Float.valueOf(request.getParameter("price")).floatValue();

                logger.userCommitSellTrigger(serverId, transId, state.username, stock, price);

                TransactionServer xs = factory.getTransactionServer(state.id);

                state.message = "Sell trigger for '" + stock + "' was added.";
                xs.commitSellTrigger(transId, state.id, stock, price);
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }

    protected void doCancelSellTrigger(HttpServletRequest request,
                                       HttpServletResponse response) throws IOException, ServletException {

        final String CMD = "CANCEL_SET_SELL";
        debugLog.debug(CMD);
        int transId = logger.getTransId();

        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            showLoginPage(request, response, "You must login first.");
        } else {
            try {
                String stock = request.getParameter("stock");

                logger.userCancelSellTrigger(serverId, transId, state.username, stock);

                TransactionServer xs = factory.getTransactionServer(state.id);

                state.message = "Sell trigger for '" + stock + "' was removed.";
                xs.cancelSellTrigger(transId, state.id, stock);
                setSessionState(state, response);
                response.sendRedirect("stockserv");
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired.");
            } catch (Exception err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }




    protected void doMainMenu(HttpServletRequest request,
                              HttpServletResponse response) throws IOException, ServletException {



        debugLog.debug("doMainMenu");
        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        if (state == null) {
            // not logged in.  Display login page
            showLoginPage(request, response, null);
        } else {
            try {
                int transId = logger.getTransId();
                showMainMenu(request, response, state, transId);
            } catch (SessionNotFoundException err) {
                setSessionState(null, response);
                showLoginPage(request, response, "Session has expired");
            }
        }
    }

    public Quote fetchQuote(int transId, long sessionId, String stockSymbol, String username) throws IOException {
	try {
	    TransactionServer xs = factory.getTransactionServer(sessionId);
	    return xs.quote(transId, sessionId, stockSymbol);
	} catch (Exception err) {
	    debugLog.error("Quote Error.", err);
	    throw new IOException(err.getMessage());
	}
    }

    protected void doQuote(HttpServletRequest request,
                           HttpServletResponse response)  throws IOException, ServletException {

        debugLog.debug("doQuote");
        final String CMD = "QUOTE";
        int transId = logger.getTransId();

        PrintWriter writer = response.getWriter();
        //HttpSession session = request.getSession();
        //SessionState state = (SessionState)session.getAttribute("State");
        SessionState state = getSessionState(request);

        state.message = null;
        if (state == null) {
            showLoginPage(request, response, "You must be logged in to perform this function.");
        } else {
            try {
                String stock = request.getParameter("stock");

                logger.userQuote(serverId, transId, state.username, stock);

		Quote quote = quoteCache.quote(transId, state.id, stock, null, this);

                writer.println("<html><body><br>Stock symbol: " + quote.stock +
                               "<br>Price: $" + String.valueOf(quote.price) +
                               "<br>Timestamp: " + Long.toString(quote.timestamp) +
                               "<br>Key: " + quote.key +
                               "<br><br><a href='stockserv'>Return</a>" +
                               "</body></html>");
            } catch (StockServException err) {
                handleError(transId, state, CMD, request, response, err);
            }
        }
    }


    protected void doLogin(HttpServletRequest request,
                           HttpServletResponse response)  throws IOException, ServletException {
        debugLog.debug("doLogin");
        //HttpSession session = request.getSession();
        SessionState oldState = getSessionState(request);
        if (oldState != null) {
            logout(oldState);
        }


        String userName = request.getParameter("username");
        String password = request.getParameter("password");

        SessionState state = new SessionState();

        try {
            TransactionServer xs = factory.getTransactionServer(0L);
            state.id = xs.openSession(userName, password);
            state.username = userName;

            // authenticated - save session
            //session.setAttribute("State", state);
            setSessionState(state, response);

            // Redirect to  Main Menu
            response.sendRedirect("stockserv");
        } catch (StockServException err) {
            // Show login page again
            setSessionState(null, response);
            showLoginPage(request, response, err.getMessage());
        }

    }

    protected void logout(SessionState state) {
        try {
            TransactionServer xs = factory.getTransactionServer(state.id);
            xs.closeSession(state.id);
        } catch (Exception err) {
        }
    }


    protected void doLogout(HttpServletRequest request,
                            HttpServletResponse response) throws IOException, ServletException {

        debugLog.debug("doLogout");
        SessionState state = getSessionState(request);
        if (state != null) {
            logout(state);
        }

        setSessionState(null, response);

        // Redirect to login page
        showLoginPage(request, response, "You have been logged out.");
    }


    protected void handleError(int transId,
                               SessionState state,
                               String cmd,
                               HttpServletRequest request,
                               HttpServletResponse response,
                               Exception err) throws IOException {

        if (state != null) {
            logger.errorEvent(serverId, transId, state.username, cmd, err.getMessage());
        }

        PrintWriter writer = response.getWriter();
        writer.println("<html><body><h1>Error</h1><pre>" +
                       err.getMessage() + "</pre></body</html>");
    }


    protected void doInit(HttpServletRequest request,
                          HttpServletResponse response)  throws IOException, ServletException {

        debugLog.debug("doInit");
        // Logout
        SessionState state = getSessionState(request);
        if (state != null) {
            logout(state);
        }

        // Init
        try {
            ServerRegistry manager = factory.getServerRegistry();
            manager.initSystem();
            //TransactionServer xs = factory.getTransactionServer(0);
            //xs.initSystem();
            setSessionState(null, response);
            request.setAttribute("message", "Init Complete");
            loadJspPage("/initComplete.jsp", request, response);
        } catch (StockServException err) {
            handleError(0, null, "", request, response, err);
        }
    }


    protected void doStatStart(HttpServletRequest request,
                               HttpServletResponse response,
                               boolean isStart)  throws IOException, ServletException {

        try {
            debugLog.debug("doStatStart - "  + (isStart ? "Starting" : "Stoping"));
            ServerRegistry reg = factory.getServerRegistry();
            if (isStart) {
                reg.startStats();
                request.setAttribute("message", "Stats Started");
            } else {
                reg.stopStats();
                request.setAttribute("message", "Stats Stopped");
            }

            loadJspPage("/initComplete.jsp", request, response);
        } catch (StockServException err) {
            handleError(0, null, "", request, response, err);
        }
    }


    protected void doStatGet(HttpServletRequest request,
                               HttpServletResponse response)  throws IOException, ServletException {

        try {
            debugLog.debug("doStatGet");
            ServerRegistry reg = factory.getServerRegistry();
            ArrayList statsList = reg.getStats();
            request.setAttribute("statsList", statsList);
            loadJspPage("/stats.jsp", request, response);
        } catch (StockServException err) {
            handleError(0, null, "", request, response, err);
        }
    }



    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException {

        response.setContentType("text/html");

        try {
            if (logger == null) {
                logger = factory.getAuditServer();
            }
        } catch (CommException err) {
            handleError(0, null, "", request, response, err);
        }

        String cmd = request.getParameter("cmd");
        if (cmd == null || cmd.length() == 0) {
            doMainMenu(request, response);
        }

        debugLog.info("Cmd: " + cmd);

        int cmdCode = (cmd == null) ? 0 : cmd.hashCode();
            System.out.println("DUMPLOG Hash Code :"+cmdCode);
        switch(cmdCode) {
        case CMD_DISPLAY_STATUS :
            doMainMenu(request, response);
            break;
        case CMD_LOGIN:
            doLogin(request, response);
            break;
        case CMD_LOGOUT:
            doLogout(request, response);
            break;
        case CMD_QUOTE:
            doQuote(request, response);
            break;
        case CMD_BUY :
            doBuy(request, response);
            break;
        case CMD_CANCEL_BUY :
            doCancelBuy(request, response);
            break;
        case CMD_COMMIT :
            doCommitBuy(request, response);
            break;
        case CMD_ADDFUNDS :
            doAddFunds(request, response);
            break;
        case CMD_SELL :
            doSell(request, response);
            break;
        case CMD_COMMIT_SELL :
            doCommitSell(request, response);
            break;
        case CMD_CANCEL_SELL :
            doCancelSell(request, response);
            break;

        case CMD_DUMPLOG :
            doDumpLog(request, response);
            break;

        case CMD_BUY_TRIGGER :
            doBuyTrigger(request, response);
            break;
        case CMD_COMMIT_BUY_TRIGGER :
            doCommitBuyTrigger(request, response);
            break;
        case CMD_CANCEL_BUY_TRIGGER :
            doCancelBuyTrigger(request, response);
            break;
        case CMD_SELL_TRIGGER :
            doSellTrigger(request, response);
            break;
        case CMD_COMMIT_SELL_TRIGGER :
            doCommitSellTrigger(request, response);
            break;
        case CMD_CANCEL_SELL_TRIGGER :
            doCancelSellTrigger(request, response);
            break;
        case CMD_MENU :
            doMainMenu(request, response);
            break;
        case CMD_INIT :
            doInit(request, response);
            break;
        case CMD_STAT_START :
            doStatStart(request, response, true);
            break;
        case CMD_STAT_STOP :
            doStatStart(request, response, false);
            break;
        case CMD_STAT_GET :
            doStatGet(request, response);
            break;
        default:
            handleError(0, null, "", request, response, new Exception("Invalid Command: " + cmd));
            break;
        }

        HttpSession session = request.getSession(false);
        if (session != null) {
            debugLog.warn("SESSION!");
            session.invalidate();
        } else {
            debugLog.warn("NO SESSION!");
        }

    }

    public void doPost(HttpServletRequest request,
                       HttpServletResponse response)
                throws ServletException, IOException {
        doGet(request, response);
    }

    protected void loadJspPage(String jspUrl, HttpServletRequest request, HttpServletResponse response)
        throws ServletException,
               IOException
    {
        getServletConfig().getServletContext().getRequestDispatcher(jspUrl).forward(request, response);
    }

}
